using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using System.Web.UI;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.InsightWebControls;
using PHSRAG.Insight21.Policy;
using PHSRAG.Security.Enumerations;
using PHSRAG.Utility;

namespace PHSRAG.Insight21.Admin
{
    /// <summary>
    /// The AdminUserAccessRights page allows system administrators, key givers, and PI's
    /// to view/edit a user's module roles and access rights.
    /// </summary>
    public partial class AdminUserAccessRights : BasePage
    {
        #region Constants

        private const string ApplicationUserTableName = "ApplicationUser";
        private const string EditModeText = "Edit";
        private const string ModuleRoleBitmask = "ModuleRoleBitmask";
        private const string OrgPickerControl = "../Admin/AdminControls/OrgAccessCOSPicker.ascx";
        private const string PickerHostPage = "../Common/ControlHost.aspx";
        private const string PIPickerControl = "../Admin/AdminControls/PIAccessPicker.ascx";
        private const string PIPickerFilterColumn = "LastName";
        private const string PIPickerLoader = "GetPIList";
        private const string RecordsPickerControl = "../Admin/AdminControls/RecordsAccessPicker.ascx";
        private const string SaveModeText = "Save";

        #endregion

        #region Instance variables (Private)

        private ICachePolicy cachePolicy;
        private ICachePolicy pageCachePolicy;

        #endregion

        #region Private Properties

        /// <summary>
        /// Gets the relevant user object from the cache if there is one otherwise loads 
        /// a new one based on the cached personID and cache's it.
        /// </summary>
        private new User User
        {
            get
            {
                User user = cachePolicy.GetCachedObject(User.CacheKey) as User;

                Hashtable h = (Hashtable) pageCachePolicy.GetCachedObject(Keys.IncomingDataKey);
                int personId = (int) h[Keys.PersonIdKey];
                if (user == null || (user.PersonId != personId))
                {
                    user = new User(cachePolicy);
                    user.Load(DataAccess.GetConnectionString(), personId);
                    user.Cache();
                }

                return user;
            }
        }

        #endregion

        #region Event handlers

        /// <summary>
        /// Event handler for the event raised when the Add button is clicked in the org AccessPrivilegeEditor control.
        /// Launch the OrgAccessCOSPicker popup if the logged in user is a system administrator or if they are
        /// a keygiver for more than one organization.  Otherwise, if the logged in user is a keygiver for one organization
        /// simply add that organization to the cached user's organization access rights (if it doesn't already
        /// exist), save the org rights, and reload the page.
        /// </summary>
        /// <param name="sender">Source of the event</param>
        /// <param name="e">Argument associated with the event.</param>
        protected void OnAddOrganizations(object sender, CommandEventArgs e)
        {
            UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);

            if (IsUserSysAdmin(userContext) || userContext.KeyGiverRights.Rows.Count > 1)
            {
                string features = string.Format("width={0},height={1},scrollbars=yes,resizable=yes,status=no",
                    Settings.GetKeyValue("SearchPopupWindow.Width", 700),
                    Settings.GetKeyValue("AdminPISearchPopupWindow.Height", 800));

                ClientScript.RegisterStartupScript(GetType(), OrgPickerControl
                    , string.Format("<script language='javascript'>window.open('{0}?Load={1}', 'COSPicker', '{2}');</script>",
                        PickerHostPage, OrgPickerControl, features));
            }
            else if (userContext.IsKeyGiver)
            {
                DataTable orgAccessTable = User.GetOrganizationRights(userContext.DomainUserId).OrganizationList;
                if (orgAccessTable.Rows.Count != 1)
                {
                    DataRow keyGiverOrgRow = userContext.KeyGiverRights.Rows[0];

                    DataRow row = orgAccessTable.NewRow();
                    row["FwkDomainOrganizationId"] = keyGiverOrgRow["Id"];
                    row["IsRecursive"] = 0;
                    row["FwkDomainUserId"] = User.DomainUserId;
                    row["RightBitmask"] = 0;
                    orgAccessTable.Rows.Add(row);

                    User.GetOrganizationRights(userContext.IsKeyGiver ? userContext.DomainUserId : 0).OrganizationList = orgAccessTable;

                    SqlConnection connection = new SqlConnection(DataAccess.ConnectionString);
                    SqlTransaction transaction = null;

                    try
                    {
                        connection.Open();
                        transaction = connection.BeginTransaction("OrganizationAccessRights");
                        User.GetOrganizationRights(userContext.IsKeyGiver ? userContext.DomainUserId : 0).Save(transaction);
                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {
                        if (transaction != null)
                        {
                            transaction.Rollback();
                        }

                        annunciator.Message = ex.Message;
                    }
                    finally
                    {
                        if (connection.State != ConnectionState.Closed)
                        {
                            connection.Close();
                        }
                    }

                    User.UnCache();
                    Response.Redirect(Settings.GetKeyValue("SubNavigation.Admin.UserDetails.UserAccessRightsURL", ""));
                }
            }
        }

        /// <summary>
        /// Event handler for the event raised when the Add button is clicked in the portfolio 
        /// AccessPrivilegeEditor control. If the logged in user is a System Administrator, launch the PIAccessPicker popup.  
        /// Otherwise, if the logged in user is a PI simply add that PI to the cached user's portfolio access rights 
        /// (if it doesn't already exist), save the org rights, and reload the page.  
        /// </summary>
        /// <param name="sender">Source of the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnAddPortfolios(object sender, CommandEventArgs e)
        {
            UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);

            if (IsUserSysAdmin(userContext))
            {
                //remove the cached selected pi data view that the picker may have populated
                Hashtable h = (Hashtable) pageCachePolicy.GetCachedObject(Keys.IncomingDataKey);
                h.Remove(Keys.PIRightsKey);

                string features = string.Format("width={0},height={1},scrollbars=yes,resizable=yes,status=no",
                    Settings.GetKeyValue("SearchPopupWindow.Width", 700),
                    Settings.GetKeyValue("AdminPISearchPopupWindow.Height", 800));

                ClientScript.RegisterStartupScript(GetType(), PIPickerControl
                    , string.Format("<script language='javascript'> window.open('{0}?Load={1}&Loader={2}&FilterColumn={3}', 'PIPicker', '{4}');</script>",
                        PickerHostPage, PIPickerControl, PIPickerLoader, PIPickerFilterColumn, features));
            }
            else if (IsUserPrincipalInvestigator(userContext))
            {
                DataTable portfolioDataTable = User.GetPortfolioRights(userContext.DomainUserId).PIList;

                if (portfolioDataTable.Rows.Count != 1)
                {
                    DataRow row = portfolioDataTable.NewRow();
                    row["Id"] = userContext.PersonId;
                    row["FwkDomainUserId"] = User.DomainUserId;
                    row["RightBitMask"] = 0;

                    portfolioDataTable.Rows.Add(row);
                    User.GetPortfolioRights(userContext.DomainUserId).PIList = portfolioDataTable;

                    SqlConnection connection = new SqlConnection(DataAccess.ConnectionString);
                    SqlTransaction transaction = null;

                    try
                    {
                        connection.Open();
                        transaction = connection.BeginTransaction("PortfolioAccessRights");
                        User.GetPortfolioRights(userContext.DomainUserId).Save(transaction);
                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {
                        if (transaction != null)
                        {
                            transaction.Rollback();
                        }

                        annunciator.Message = ex.Message;
                    }
                    finally
                    {
                        if (connection.State != ConnectionState.Closed)
                        {
                            connection.Close();
                        }
                    }

                    User.UnCache();
                    Response.Redirect(Settings.GetKeyValue("SubNavigation.Admin.UserDetails.UserAccessRightsURL", ""));
                }
            }
        }

        /// <summary>
        /// Event handler for the event raised when the Add button is clicked in the records AccessPrivilegeEditor control.
        /// Launches aunch the RecordsAccessPicker popup.    
        /// </summary>
        /// <param name="sender">Source of the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnAddRecords(object sender, CommandEventArgs e)
        {
            //remove the cached selected record data view that the picker may have populated
            Hashtable h = (Hashtable) pageCachePolicy.GetCachedObject(Keys.IncomingDataKey);
            h.Remove(Keys.RecordRightsKey);

            string features = string.Format("width={0},height={1},scrollbars=yes,resizable=yes,status=no",
                Settings.GetKeyValue("SearchPopupWindow.Width", 700),
                Settings.GetKeyValue("AdminPISearchPopupWindow.Height", 800));

            ClientScript.RegisterStartupScript(GetType(), RecordsPickerControl
                , string.Format("<script language='javascript'>window.open('{0}?Load={1}', 'RecordsPicker', '{2}');</script>",
                    PickerHostPage, RecordsPickerControl, features));
        }

        /// <summary>
        /// This is the handler for the event that is fired when the Edit/Save button is clicked.  If
        /// the button's text is "Edit" we are entering edit mode so the checkboxes in the 
        /// ModuleRole data grid that were disabled will now get enabled and the button's text toggled to "Save".
        /// Further, the access editor controls on the page are enabled for editing.  
        /// If we are in save mode: 
        ///				If the user is a sys admin, save everything
        ///				If the user is a PI, save portfolio and record access
        ///				If the user is a keygiver, save org and record access
        /// </summary>
        /// <param name="sender">Source of the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnEditSave(object sender, EventArgs e)
        {
            if (editSave.Text == EditModeText)
            {
                SetModuleRolesCheckBoxEnabled(true);
                orgAccessEditor.EnableEdit = portfolioAccessEditor.EnableEdit = recordAccessEditor.EnableEdit = true;
                editSave.Text = SaveModeText;
                lastName.CssClass = "alert";
            }
            else
            {
                UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);

                SqlConnection connection = new SqlConnection(DataAccess.ConnectionString);
                SqlTransaction transaction = null;
                lastName.CssClass = "";

                try
                {
                    connection.Open();
                    transaction = connection.BeginTransaction("AdminUserAccessRights");

                    bool isUserSysAdmin = IsUserSysAdmin(userContext);
                    //save org access first because the stored proc contains 
                    //some validation around keygiver rights...if validation
                    //fails, don't save anything at all and inform the user
                    if (userContext.IsKeyGiver || isUserSysAdmin)
                    {
                        SaveOrganizationAccessRights(transaction);
                        orgAccessEditor.EnableEdit = false;
                    }
                    if (isUserSysAdmin)
                    {
                        SaveModuleRoles(transaction);
                        SetModuleRolesCheckBoxEnabled(false);
                    }
                    if (IsUserPrincipalInvestigator(userContext) || isUserSysAdmin)
                    {
                        SavePortfolioAccessRights(transaction);
                        portfolioAccessEditor.EnableEdit = false;
                    }

                    SaveRecordAccessRights(transaction);
                    recordAccessEditor.EnableEdit = false;

                    User.UpdateUserResourceCache(transaction);

                    transaction.Commit();

                    editSave.Text = EditModeText;
                    User.UnCache();
                    recordAccessEditor.Refresh();
                }
                catch (Exception ex)
                {
                    if (transaction != null)
                    {
                        transaction.Rollback();
                    }

                    annunciator.Message = ex.Message;
                }
                finally
                {
                    if (connection.State != ConnectionState.Closed)
                    {
                        connection.Close();
                    }
                }
            }
        }

        /// <summary>
        /// Resets the subnavigation selected link(s) before the 
        /// header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnHeaderNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
            adminUserManagementSubNavigation.Reset();
        }

        protected void OnSubNavigationNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
        }

        /// <summary>
        /// Sets the "Selected" checkbox column on the datagrid based on the value of 
        /// the "IsSelected" column of the DataGridItem.  Also disables all checkboxes.
        /// </summary>
        /// <param name="sender">dataGrid</param>
        /// <param name="e">DataGridItem</param>
        protected void OnModuleRolesItemDataBound(object sender, DataGridItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {
                ((CheckBox) (e.Item.Cells[4]).Controls[1]).Checked = Convert.ToBoolean(User.ModuleRolesAccess.Details.Select(String.Format("Role = '{0}'", e.Item.Cells[2].Text))[0]["IsSelected"]);
                ((CheckBox) (e.Item.Cells[4]).Controls[1]).Enabled = false;
            }
        }

        /// <summary>
        /// All actions here are on non-postbacks only. The breadcrumb trail gets set.
        /// We remove previously selected PI's and Records from the cache here so when the 
        /// PI and Record access popups launch they are refreshed.  Basic user profile
        /// information is set on some of the page's controls.  
        /// If the logged in user is a:
        ///		System Administrator - display all page's controls.
        ///		PI - display only record and portfolio (PI) access privilege editors
        ///		KeyGiver - display only record and organization access privilege editors
        ///	Only show the Edit/Save button if the user is registered.
        /// <param name="sender">sender of the event</param>
        /// <param name="e">arguments of the event</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            bodyTag.Attributes["onbeforeunload"] = "ExitWarning()";
            annunciator.Message = string.Empty;

            if (!IsPostBack)
            {
                try
                {
                    breadCrumb.Add("Access Rights", "AdminUserAccessRights.aspx", Settings.GetKeyValue("BreadCrumb.Admin.AdminUserAccessRightsPageLevel", 2));

                    lastName.Text = User.LastName;
                    firstName.Text = User.FirstName;
                    userName.Text = User.Username;
                    organization.Text = User.Organization;

                    UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);

                    if (IsUserSysAdmin(userContext))
                    {
                        //sysadmins can view/edit everything
                        moduleRoleDataGrid.DataSource = User.ModuleRolesAccess.DetailsForUI;
                        moduleRoleDataGrid.DataBind();
                    }
                    else
                    {
                        //user is not a sys admin
                        //only sys adimins can view/edit module roles
                        moduleRolesLabel.Visible = moduleRoleDataGrid.Visible = editSave.Visible = false;

                        if (!userContext.IsKeyGiver)
                        {
                            //only sysadmin and key givers can view/edit org access	
                            orgLabel.Visible = orgAccessEditor.Visible = false;

                            if (!IsUserPrincipalInvestigator(userContext))
                            {
                                //only users that are sysadmin or key givers or PI's can view/edit record access	
                                recordsLabel.Visible = recordAccessEditor.Visible = false;
                            }
                        }

                        if (!IsUserPrincipalInvestigator(userContext))
                        {
                            //only users that are sysadmin or PI's can view/edit portfolio access
                            portfolioLabel.Visible = portfolioAccessEditor.Visible = false;
                        }
                    }

                    if ((cachePolicy.GetCachedObject(Keys.SaveEditStateKey)) != null)
                    {
                        SetModuleRolesCheckBoxEnabled(true);
                        orgAccessEditor.EnableEdit = portfolioAccessEditor.EnableEdit = recordAccessEditor.EnableEdit = true;
                        lastName.CssClass = "alert";
                        editSave.Text = "Save";
                    }

                    if (!User.IsRegistered)
                    {
                        //nothing can be edited on an unregistered user
                        editSave.Visible = false;
                        annunciator.Message = "This user is not registered.";
                    }
                }
                catch (Exception ex)
                {
                    annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
                    ExceptionReport.WriteToEventLog("AdminUserAccessRights", ex, true, ExceptionReport.ReportType.Error);
                }
            }
        }

        /// <summary>
        /// Event handler for the event raised when the org AccessPrivilegeEditor needs the item list.
        /// The item caption is supplied and the cached user's organization rights details are returned.
        /// Note that if the logged in user is a System Admin we can display all of the user's org
        /// access rights.  However, if the user is just a KeyGiver we will display only those rights tied to
        /// organizations that the user is KeyGiver for. 
        /// </summary>
        /// <returns>DataTable containing names of all items</returns>
        protected DataTable OnProvideOrgItemList(AccessPrivilegeEditor editor, out string itemCaption)
        {
            itemCaption = "Organizations";
            UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);
            return User.GetOrganizationRights(IsUserSysAdmin(userContext) ? 0 : (userContext.IsKeyGiver) ? userContext.DomainUserId : 0).Details;
        }

        /// <summary>
        /// Event handler for the event raised when the portfolio AccessPrivilegeEditor needs the item list.
        /// The item caption is supplied and the cached user's organization rights details are returned.
        /// Note that if the logged in user is a System Admin we can display all of the user's portfolio
        /// access rights.  However, if the user is just a PI we will only display the user's rights for
        /// that PI. 
        /// </summary>
        /// <returns>DataTable containing names of all items</returns>
        protected DataTable OnProvidePortfolioItemList(AccessPrivilegeEditor editor, out string itemCaption)
        {
            itemCaption = "Principal Investigators";
            UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);
            return User.GetPortfolioRights(IsUserSysAdmin(userContext) ? 0 : (IsUserPrincipalInvestigator(userContext)) ? userContext.DomainUserId : 0).RightsDetails;
        }

        /// <summary>
        /// Event handler for the event raised when the record AccessPrivilegeEditor needs the item list.
        /// The item caption is supplied and the cached user's organization rights details are returned.
        /// Note that if the logged in user is a System Admin we can display all of the user's direct
        /// access rights.  However, if the user is just a PI we will only display the user's direct access
        /// rights for records owned by that PI.  Further if the logged in user is a keygiver we will display 
        /// only those rights tied to organizations that the user is KeyGiver for. 
        /// </summary>
        /// <returns>DataTable containing names of all items</returns>
        protected DataTable OnProvideRecordItemList(AccessPrivilegeEditor editor, out string itemCaption)
        {
            itemCaption = "Records";
            UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);
            return User.GetDirectAccessRights(IsUserSysAdmin(userContext) ? 0 : (IsUserPrincipalInvestigator(userContext)) ? userContext.DomainUserId : 0,
                IsUserSysAdmin(userContext) ? 0 : (userContext.IsKeyGiver) ? userContext.DomainUserId : 0).RightsDetails;
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Used to determine if the user is a Principal Investigator
        /// </summary>
        /// <param name="userContext">The user context information to be evaluated.</param>
        /// <returns>True if the user is a PI otherwise False</returns>
        private bool IsUserPrincipalInvestigator(UserContext userContext)
        {
            return ((userContext.ModuleRoleBitmask & (int) ModuleRoleBit.PrincipalInvestigator) != 0);
        }

        /// <summary>
        /// Used to determine if the user is a System Administrator
        /// </summary>
        /// <param name="userContext">The user context information to be evaluated.</param>
        /// <returns>True if the user is a System Administrator otherwise False</returns>
        private bool IsUserSysAdmin(UserContext userContext)
        {
            return ((userContext.ModuleRoleBitmask & (int) ModuleRoleBit.SystemAdministrator) != 0);
        }


        /// <summary>
        /// Persists ModuleRole updates to the database.
        /// </summary>
        private void SaveModuleRoles(SqlTransaction transaction)
        {
            int moduleRoleBitmask = 0;
            DataTable applicationUserTable = User.ApplicationUserDetail.GetDataContainer().Tables[ApplicationUserTableName];
            DataRow[] rows = User.ModuleRolesAccess.Details.Select(String.Format("IsGrantedViaUI = 0"));

            foreach (DataRow row in rows)
            {
                if ((Convert.ToInt32(row["BitValue"]) & Convert.ToInt32(applicationUserTable.Rows[0][ModuleRoleBitmask])) > 0)
                {
                    moduleRoleBitmask += Convert.ToInt32(row["BitValue"]);
                }
            }

            foreach (DataGridItem item in moduleRoleDataGrid.Items)
            {
                if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
                {
                    if (((CheckBox) (item.Cells[4]).Controls[1]).Checked)
                    {
                        moduleRoleBitmask += Convert.ToInt32(item.Cells[0].Text);
                    }
                }
            }

            applicationUserTable.Rows[0][ModuleRoleBitmask] = moduleRoleBitmask;

            User.ApplicationUserDetail.Save(DataAccess.GetConnectionString());
        }

        /// <summary>
        /// Persists Organization Access Rights updates to the database.
        /// </summary>
        private void SaveOrganizationAccessRights(SqlTransaction transaction)
        {
            //save org items
            Hashtable orgAccessItems = orgAccessEditor.CurrentState.Items;
            if (orgAccessItems.Count > 0)
            {
                UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);
                DataTable orgDataTable = User.GetOrganizationRights(userContext.IsKeyGiver ? userContext.DomainUserId : 0).OrganizationList;

                foreach (string key in orgAccessItems.Keys)
                {
                    Pair item = (Pair) orgAccessItems[key];
                    //						Legend:
                    //							item.First = org's FwkDomainOrganizationId
                    //							item.Second = AccessRightBitmask

                    DataRow[] rows = orgDataTable.Select(String.Format("FwkDomainOrganizationId = {0}", item.First));
                    if (rows.Length > 0)
                    {
                        DataRow row = rows[0];
                        if (row["RightBitmask"] != item.Second)
                        {
                            row["RightBitmask"] = item.Second;
                        }
                    }
                }
                //persist Org access changes
                User.GetOrganizationRights(userContext.IsKeyGiver ? userContext.DomainUserId : 0).Save(transaction);
            }
        }

        /// <summary>
        /// Persists Portfolio (PI) Access Rights updates to the database.
        /// </summary>
        private void SavePortfolioAccessRights(SqlTransaction transaction)
        {
            //save portfolio items
            Hashtable portfolioAccessItems = portfolioAccessEditor.CurrentState.Items;

            if (portfolioAccessItems.Count > 0)
            {
                UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);
                DataTable portfolioDataTable = User.GetPortfolioRights(IsUserPrincipalInvestigator(userContext) ? userContext.DomainUserId : 0).PIList;
                foreach (string key in portfolioAccessItems.Keys)
                {
                    Pair item = (Pair) portfolioAccessItems[key];
                    //						Legend:
                    //							item.First = PI's AdmPerson ID
                    //							item.Second = AccessRightBitmask

                    DataRow[] rows = portfolioDataTable.Select(String.Format("Id = {0}", item.First));
                    if (rows.Length > 0)
                    {
                        DataRow row = rows[0];
                        if (row["RightBitmask"] != item.Second)
                        {
                            row["RightBitmask"] = item.Second;
                        }
                    }
                }
                //persist Portfolio access changes
                User.GetPortfolioRights(IsUserPrincipalInvestigator(userContext) ? userContext.DomainUserId : 0).Save(transaction);
            }
        }

        /// <summary>
        /// Persists Record (direct) Access Rights updates to the database.
        /// </summary>
        private void SaveRecordAccessRights(SqlTransaction transaction)
        {
            //save Record items
            Hashtable recordAccessItems = recordAccessEditor.CurrentState.Items;

            if (recordAccessItems.Count > 0)
            {
                UserContext userContext = (UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey);

                DataTable recordsDataTable = User.GetDirectAccessRights(
                    IsUserPrincipalInvestigator(userContext) ? userContext.DomainUserId : 0,
                    userContext.IsKeyGiver ? userContext.DomainUserId : 0).RecordList;

                foreach (string key in recordAccessItems.Keys)
                {
                    Pair item = (Pair) recordAccessItems[key];
                    Triplet triplet = (Triplet) item.Second;
                    //						Legend:
                    //							item.First = resourceID
                    //							triplet.First = bitmask
                    //							triplet.Second = isContact
                    //							triplet.Third = Comment

                    DataRow[] rows = recordsDataTable.Select(String.Format("ResourceId = {0}", item.First));
                    if (rows.Length > 0)
                    {
                        DataRow row = rows[0];
                        if (row["AccessRightBitMask"] != triplet.First)
                        {
                            row["AccessRightBitMask"] = triplet.First;
                        }

                        if (row["Is Contact"] != triplet.Second)
                        {
                            row["Is Contact"] = triplet.Second;
                        }

                        if (row["Comment"] != triplet.Third)
                        {
                            row["Comment"] = triplet.Third;
                        }
                    }
                }
                User.GetDirectAccessRights(
                    IsUserPrincipalInvestigator(userContext) ? userContext.DomainUserId : 0,
                    userContext.IsKeyGiver ? userContext.DomainUserId : 0).Save(transaction);
            }
        }

        /// <summary>
        /// Disables/Enables the Module Role checkbox column in the moduleRoleDataGrid based on the passed in 
        /// boolean parameter value.
        /// </summary>
        /// <param name="isEnabled">Indicator used to enable/disable the checkbox column.</param>
        private void SetModuleRolesCheckBoxEnabled(bool isEnabled)
        {
            //toggle to edit mode
            foreach (DataGridItem item in moduleRoleDataGrid.Items)
            {
                if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
                {
                    ((CheckBox) (item.Cells[4]).Controls[1]).Enabled = isEnabled;
                }
            }
        }

        private void PurgeCache()
        {
            ResultsCache.PurgeObject(cachePolicy);
            cachePolicy.UnCache(Keys.SaveEditStateKey);
        }

        #endregion

        #region Web Form Designer generated code

        /// <summary>
        /// Initializes page members/components
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);
            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.header.Attributes["OnClick"] = "warn = true;";
            this.adminUserManagementSubNavigation.Attributes["OnClick"] = "warn = true;";
            this.breadCrumb.Attributes["OnClick"] = "warn = true;";
        }

        #endregion
    }
}